package PCLiveServer

import (
	"encoding/json"
	"log"
	"net"
	"strings"
	"sync"
	"time"
)

type struct_message struct {
	mess []byte
	len  int
	addr *net.UDPAddr
}

type jsonmessage struct {
	UserName string
	MAC      string
	HostName string
	Date     string
}

var LogFile *log.Logger
var PacketPool sync.Pool
var ReadBuffPool sync.Pool

func ServerThread(message chan struct_message, conn *net.UDPConn) {
	for {
		tmp := ReadBuffPool.Get().([]byte)
		packet := PacketPool.Get().(struct_message)
		n, raddr, err := conn.ReadFromUDP(tmp)
		if err != nil {
			LogFile.Println(err)
			return
		}

		if n > 0 {
			packet.addr = raddr
			packet.mess = tmp
			packet.len = n
			message <- packet
		}
	}
}

func PacketDial(message chan struct_message) {
	for {
		packet := <-message

		// 解析数据
		var mess jsonmessage
		if err := json.Unmarshal(packet.mess[0:packet.len], &mess); err != nil {
			// 释放资源
			ReadBuffPool.Put(packet.mess)
			PacketPool.Put(packet)
			LogFile.Println("解析文字串失败" + string(packet.mess[0:packet.len]))
			continue
		}

		mess.UserName = strings.ToUpper(mess.UserName)
		// 判断用户是否存在
		if !UserExist(mess.UserName) {
			// 释放资源
			ReadBuffPool.Put(packet.mess)
			PacketPool.Put(packet)
			LogFile.Println("不存在的用户" + mess.UserName)
			continue
		}

		// 获取在线信息
		OnlinePCList, haveGet := GetOnlineWithMac(mess.MAC)
		if !haveGet {
			LogFile.Println("新信息-" + mess.UserName + "-" + mess.MAC)
			// 如果没有那么是新的，直接插入online和data
			var insertOnline OnlineStruct
			insertOnline.UserName = mess.UserName
			insertOnline.MAC = mess.MAC
			insertOnline.HostName = mess.HostName
			insertOnline.CurrentTime = time.Now()
			insertOnline.StartTime = insertOnline.CurrentTime
			// 插入
			InsertOnline(insertOnline)

			// 释放资源
			ReadBuffPool.Put(packet.mess)
			PacketPool.Put(packet)
			continue
		}

		// 否则判断online是否过期
		// 这里有个问题就是Now的时间和字符串转的时间是不一致的，所以这里的now先获取字符串在转回来
		bef, _ := time.ParseDuration("-1m")
		nowtimestring := time.Now().Format("2006-01-02 15:04:05")
		nowtime, _ := time.Parse("2006-01-02 15:04:05", nowtimestring)
		oneMhbef := nowtime.Add(bef)
		cut := OnlinePCList[0].CurrentTime

		// 计算starttime 是否是昨天
		SameDay := OnlinePCList[0].StartTime.Day() == time.Now().Day()

		// 过期了，或者不是同一天
		if cut.Before(oneMhbef) || !SameDay {
			LogFile.Println("提交信息-" + mess.UserName + "-" + mess.MAC)
			// 过期了则更新online和data
			DeleteOnline(mess.MAC)

			var insertOnline OnlineStruct
			insertOnline.UserName = mess.UserName
			insertOnline.MAC = mess.MAC
			insertOnline.HostName = mess.HostName
			insertOnline.CurrentTime = time.Now()
			insertOnline.StartTime = insertOnline.CurrentTime
			// 插入
			InsertOnline(insertOnline)

			InsertData(OnlinePCList[0])
		} else {
			// 否则置更新online
			LogFile.Println("更新信息-" + mess.UserName + "-" + mess.MAC)
			UpdateOnline(mess.MAC, nowtimestring)
		}

		// 释放资源
		ReadBuffPool.Put(packet.mess)
		PacketPool.Put(packet)
	}
}

func InitPCLiveServer(logger *log.Logger) {
	// 日志文件初始化
	LogFile = logger

	// 创建缓冲区
	ReadBuffPool.New = func() interface{} {
		return make([]byte, 512)
	}
	PacketPool.New = func() interface{} {
		var tmp struct_message
		return tmp
	}

	// 初始化监听地址
	udp_addr, err := net.ResolveUDPAddr("udp", ":7788")
	if err != nil {
		LogFile.Println(err)
		return
	}

	// 监听地址
	conn, err := net.ListenUDP("udp", udp_addr)
	if err != nil {
		LogFile.Println(err)
		return
	}
	// defer conn.Close()

	//开启监听服务
	Message := make(chan struct_message, 512)
	go PacketDial(Message)
	go ServerThread(Message, conn)
}
